import { EChartOption, ECharts, EChartTitleOption } from "echarts";

import './index.less';
import { ChartConfig, IDataItemModel } from "./models/define";
import { StatisticUnit } from "./statistic";
import { ToolBoxUnit } from "./toolbox";

const containerClassName = 'my-monitor-charts';

/**
 * init class 
 */
export class Init {
    public myChart!: ECharts;

    private $info: JQuery<HTMLElement>;
    private $canvasContainer: JQuery<HTMLDivElement>;
    private statisticUnit: StatisticUnit;
    private toolboxUnit: ToolBoxUnit;

    private option: EChartOption = {
        title: {
            left: 'center',
            text: 'Monitor',
            // textStyle: {
            //     color: 'red'
            // }
        },
        legend: {
            type: 'scroll',
            show: false,
            // right: '5',
            top: 'center',
            orient: 'vertical',
            textStyle: {
                color: 'red'
            }
        },
        tooltip: {
            trigger: 'axis',
            // position: function (pt) {
            //     return [pt[0], '10%'];
            // }
        },
        // toolbox: {
        //     feature: {
        //         dataZoom: {
        //             yAxisIndex: 'none'
        //         },
        //         restore: {},
        //         saveAsImage: {}
        //     }
        // },
        xAxis: {
            type: 'time',
            boundaryGap: false,
            axisLabel: {},

            name: 'name',
            nameTextStyle: {
                color: 'red'
            },
            nameGap: 0
        },
        yAxis: {
            type: 'value',
            name: 'val'
            // boundaryGap: [0, '100%']
        },
        grid: {
            left: 50,
            right: 35,
            bottom: 35
        },
        // dataZoom: [{
        //     type: 'inside',
        //     start: 0,
        //     end: 100
        // }, {
        //     start: 0,
        //     end: 100
        // }],
        // series: [
        //     {
        //         name: '模拟数据',
        //         type: 'line',
        //         //smooth: true,
        //         symbol: 'none',
        //         // areaStyle: {},
        //         data: data
        //     }
        // ]
        // series: mockSeries
    };

    constructor(private dom: HTMLDivElement, private config: ChartConfig, private echartConfig?: any) {
        this.config = $.extend(true, {}, new ChartConfig(), this.config, echartConfig);

        $(dom).addClass(containerClassName);

        this.$canvasContainer = $('<div class="chart-canvas-container"></div>');
        $(dom).append(this.$canvasContainer);

        this.$info = $('<div class="chart-info"></div>');
        $(dom).append(this.$info);

        this.init();

        this.statisticUnit = new StatisticUnit(this.myChart, this.$info, this.dom);
        this.statisticUnit.calcStatistic();

        this.toolboxUnit = new ToolBoxUnit(this.myChart, this.$canvasContainer, this.config, dom);
    }

    private init() {
        // if (this.config.legendPosition === 'bottom') {
        //     this.option.grid = {
        //         left: 50,
        //         right: 50,
        //         bottom: 300
        //     };
        //     this.option.legend!.bottom = '5';
        //     this.option.legend!.left = '0';
        // } else {
        //     this.option.legend!.right = '5';
        //     this.option.legend!.top = 'center';
        //     this.option.grid = {
        //         left: 50,
        //         right: 125
        //     };
        // }

        if (this.config.legendPosition === 'bottom') {
            $(this.dom).addClass('bottom-info');
            this.$info.height(this.config.infoHeight);
        } else {
            $(this.dom).addClass('right-info');
            this.$info.width(this.config.infoWidth);
        }

        (this.option.title as EChartTitleOption).text = this.config.title;
        (this.option.yAxis as EChartOption.YAxis).name = this.config.unit;

        if (this.config.timeAxisFormatter) {
            (this.option.xAxis as EChartOption.XAxis).axisLabel!.formatter = (value: any, index: number) => {
                try {
                    let tempDate = new Date(value);
                    return dateFormatter(tempDate, this.config.timeAxisFormatter);
                } catch (e) {
                    console.error('value formatter fail,', value);
                    return '';
                }
            };
        }

        this.myChart = echarts.init(this.$canvasContainer[0]);

        this.myChart.setOption(this.option);

        this.ckeckResizeEvent();
    }

    private ckeckResizeEvent() {
        if ($(this.dom).attr('pre-width') != $(this.dom).width() ||
            $(this.dom).attr('pre-height') != $(this.dom).height()) {
            this.onResize();
            $(this.dom).attr('pre-width', $(this.dom).width() as any);
            $(this.dom).attr('pre-height', $(this.dom).height() as any);
        }

        setTimeout(() => {
            this.ckeckResizeEvent();
        }, 500);
    }
    private onResize() {
        this.myChart.resize();
        this.statisticUnit?.fixContentWidth();
    }

    public setData(data: IDataItemModel[]) {
        let mockSeries = data.map((item) => {
            return {
                name: item.target,
                data: item.datapoints.map((item2) => {
                    return [item2[1], item2[0]]
                }),
                type: 'line',
                symbol: 'none',
                smooth: true,
                areaStyle: this.config.seriesAreaStyle
                // lineStyle: {
                //     normal: {
                //         color: '#ccc'
                //     }
                // }
            };
        });
        this.myChart.setOption({
            series: mockSeries
        });
        this.statisticUnit.calcStatistic();
    }

    /**
     * on selected day view
     * @param cb event callback
     */
    public onSelectDayView(cb: () => void) {
        this.toolboxUnit.dayClickEvents.push(cb);
    }

    public onSelectWeekView(cb: () => void) {
        this.toolboxUnit.weekClickEvents.push(cb);
    }

    public onSelectMonthView(cb: () => void) {
        this.toolboxUnit.monthClickEvents.push(cb);
    }

    public selectDayMode() {
        this.toolboxUnit.selectMode('day');
    }

    public selectWeekMode() {
        this.toolboxUnit.selectMode('week');
    }

    public selectMonthMode() {
        this.toolboxUnit.selectMode('month');
    }
}

// 将 Date 转化为指定格式的String
// 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符
// 年(y)可以用 1-4 个占位符，毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
// 例子：
// "yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423
// "yyyy-M-d h:m:s.S") ==> 2006-7-2 8:9:4.18
function dateFormatter(date: Date, fmt: string) { // author: meizz
    let config: any = {
        "M+": date.getMonth() + 1,                 // 月份
        "d+": date.getDate(),                    // 日
        "h+": date.getHours(),                   // 小时
        "m+": date.getMinutes(),                 // 分
        "s+": date.getSeconds(),                 // 秒
        "q+": Math.floor((date.getMonth() + 3) / 3), // 季度
        "S": date.getMilliseconds()             // 毫秒
    };
    if (/(y+)/.test(fmt))
        fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
    for (let key in config)
        if (new RegExp("(" + key + ")").test(fmt)) {
            let replaceStr: any = '';
            if (RegExp.$1.length === 1) {
                replaceStr = config[key];
            } else {
                replaceStr = ("00" + config[key]).substr(("" + config[key]).length);
            }
            fmt = fmt.replace(RegExp.$1, replaceStr);
        }
    return fmt;
}